package com.maistars.spider.controller;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.maistars.spider.common.exception.TopicSpiderException;
import com.maistars.spider.repository.model.CrawlerSiteRulePO;
import com.maistars.spider.service.domain.rule.FieldRule;
import com.maistars.spider.service.domain.rule.PageRule;
import com.maistars.spider.service.domain.task.CrawlerTask;
import com.maistars.spider.repository.dao.CrawlerTaskDao;
import com.maistars.spider.repository.model.CrawlerFieldRulePO;
import com.maistars.spider.repository.model.CrawlerPageRulePO;
import com.maistars.spider.repository.model.CrawlerTaskPO;
import com.maistars.spider.service.template.TaskTemplate;
import com.maistars.spider.service.template.TaskTemplateResult;
import com.maistars.spider.view.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author dhr
 * @date 2021/10/10 下午6:28
 */
@Controller
@RequestMapping("/task")
@Slf4j
public class TaskController {

    @Autowired
    private CrawlerTaskDao crawlerTaskDao;

    @RequestMapping("/createTaskAndSiteRule")
    @ResponseBody
    public ResponseResult<Long> createTaskAndSiteRule(HttpServletRequest request) throws TopicSpiderException {
        ResponseResult<Long> responseResult = new ResponseResult<>();
        responseResult.setCode(100);

        String taskName = request.getParameter("taskName");
        String comment = request.getParameter("comment");

        String siteRuleName = request.getParameter("siteRuleName");
        String siteRule = request.getParameter("siteRule");
        String cronConfig = request.getParameter("cronConfig");
        String executionStartTime = request.getParameter("executionStartTime");
        String executionEndTime = request.getParameter("executionEndTime");

        CrawlerTaskPO crawlerTaskPO = new CrawlerTaskPO();
        crawlerTaskPO.setTaskName(taskName);
        crawlerTaskPO.setComment(comment);
        crawlerTaskPO.setPriority(0);
        crawlerTaskPO.setStatus(0);

        try {
            crawlerTaskDao.createCrawlerTask(crawlerTaskPO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("增加任务模板出错");
            log.error("create task occured error", e);
            return responseResult;
        }

        CrawlerSiteRulePO siteRulePO = new CrawlerSiteRulePO();
        siteRulePO.setRuleName(siteRuleName);
        siteRulePO.setTaskId(crawlerTaskPO.getId());
        siteRulePO.setSiteRule(siteRule);
        siteRulePO.setCronConfig(cronConfig);
        if (StringUtils.isNotBlank(executionStartTime)) {
            siteRulePO.setExecutionStartTime(new Date(Long.valueOf(executionStartTime)));
        }
        if (StringUtils.isNotBlank(executionEndTime)) {
            siteRulePO.setExecutionEndTime(new Date(Long.valueOf(executionEndTime)));
        }

        try {
            crawlerTaskDao.createCrawlerSiteRule(siteRulePO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("创建站点规则出错");
            log.error("create site rule occured error", e);
            return responseResult;
        }

        // 更新任务状态为"完成跟站点规则关联"
        crawlerTaskPO = new CrawlerTaskPO();
        crawlerTaskPO.setId(siteRulePO.getTaskId());
        crawlerTaskPO.setStatus(1);

        try {
            crawlerTaskDao.updateCrawlerTask(crawlerTaskPO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("创建站点规则出错");
            log.error("create site rule occured error", e);
            return responseResult;
        }
        responseResult.setData(Long.valueOf(crawlerTaskPO.getId()));
        return responseResult;
    }

    @RequestMapping("/deleteTaskAndSiteRule")
    @ResponseBody
    public ResponseResult<Long> deleteTaskAndSiteRule(HttpServletRequest request) throws TopicSpiderException {
        ResponseResult<Long> responseResult = new ResponseResult<>();
        responseResult.setCode(100);

        String taskId = request.getParameter("taskId");

        try {
            // 更新任务模板信息
            CrawlerTaskPO crawlerTaskPO = crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId));
            if (crawlerTaskPO == null) {
                responseResult.setCode(400);
                responseResult.setMsg("未查到" + taskId + "任务模板，更新任务模板出错");
                return responseResult;
            }
            CrawlerTaskPO newCrawlerTaskPO = new CrawlerTaskPO();
            newCrawlerTaskPO.setId(crawlerTaskPO.getId());
            newCrawlerTaskPO.setStatus(-1);
            crawlerTaskDao.updateCrawlerTask(newCrawlerTaskPO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("删除任务模板出错");
            log.error("delete task occured error", e);
            return responseResult;
        }

        try {
            List<CrawlerSiteRulePO> siteRulePOs = crawlerTaskDao.listCrawlerSiteRules(Integer.parseInt(taskId));
            for(CrawlerSiteRulePO crawlerSiteRulePO:siteRulePOs){
                CrawlerSiteRulePO newSiteRulePO = new CrawlerSiteRulePO();
                newSiteRulePO.setId(crawlerSiteRulePO.getId());
                newSiteRulePO.setStatus(-1);
                crawlerTaskDao.updateCrawlerSiteRule(newSiteRulePO);
            }
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("删除站点规则出错");
            log.error("delete site rule occured error", e);
            return responseResult;
        }

        responseResult.setData(Long.valueOf(taskId));
        return responseResult;
    }

    @RequestMapping("/updateTaskAndSiteRule")
    @ResponseBody
    public ResponseResult<Long> updateTaskAndSiteRule(HttpServletRequest request) throws TopicSpiderException {
        ResponseResult<Long> responseResult = new ResponseResult<>();
        responseResult.setCode(100);

        String taskId = request.getParameter("taskId");
        String siteRuleId = request.getParameter("siteRuleId");

        String taskName = request.getParameter("taskName");
        String comment = request.getParameter("comment");

        String siteRuleName = request.getParameter("siteRuleName");
        String siteRule = request.getParameter("siteRule");
        String cronConfig = request.getParameter("cronConfig");
        String executionStartTime = request.getParameter("executionStartTime");
        String executionEndTime = request.getParameter("executionEndTime");

        try {
            // 更新任务模板信息
            CrawlerTaskPO crawlerTaskPO = crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId));
            if (crawlerTaskPO == null) {
                responseResult.setCode(400);
                responseResult.setMsg("未查到" + taskId + "任务模板，更新任务模板出错");
                return responseResult;
            }
            crawlerTaskPO.setTaskName(taskName);
            crawlerTaskPO.setComment(comment);
            crawlerTaskDao.updateCrawlerTask(crawlerTaskPO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("更新任务模板出错");
            log.error("update task occured error", e);
            return responseResult;
        }

        try {
            CrawlerSiteRulePO siteRulePO = crawlerTaskDao.getCrawlerSiteRule(Integer.parseInt(siteRuleId));
            siteRulePO.setRuleName(siteRuleName);
            siteRulePO.setSiteRule(siteRule);
            siteRulePO.setCronConfig(cronConfig);
            if (StringUtils.isNotBlank(executionStartTime)) {
                siteRulePO.setExecutionStartTime(new Date(Long.valueOf(executionStartTime)));
            }
            if (StringUtils.isNotBlank(executionEndTime)) {
                siteRulePO.setExecutionEndTime(new Date(Long.valueOf(executionEndTime)));
            }
            crawlerTaskDao.updateCrawlerSiteRule(siteRulePO);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("创建站点规则出错");
            log.error("create site rule occured error", e);
            return responseResult;
        }

        responseResult.setData(Long.valueOf(taskId));
        return responseResult;
    }

    @GetMapping("/data/listAllTasks")
    @ResponseBody
    public ResponseResult<List<Map<String, String>>> listAllTasks(HttpServletRequest request) {
        int page = Integer.parseInt(request.getParameter("page"));
        int limit = Integer.parseInt(request.getParameter("limit"));

        ResponseResult<List<Map<String, String>>> responseResult = new ResponseResult<>();
        responseResult.setData(new ArrayList<>());
        responseResult.setCode(0);
        try {
            PageHelper.startPage(page,limit);
            List<CrawlerTaskPO> crawlerTaskPOS = crawlerTaskDao.listCrawlerTasks();
            if (crawlerTaskPOS == null) {
                return responseResult;
            }
            PageInfo<CrawlerTaskPO> pageInfo = new PageInfo<>(crawlerTaskPOS);
            responseResult.setCount(pageInfo.getTotal());

            for (CrawlerTaskPO crawlerTaskPO :
                    crawlerTaskPOS) {
                Map<String,String> taskDetail = new HashMap<>();
                taskDetail.put("id",String.valueOf(crawlerTaskPO.getId()));
                taskDetail.put("priority",String.valueOf(crawlerTaskPO.getPriority()));
                taskDetail.put("status",String.valueOf(crawlerTaskPO.getStatus()));
                taskDetail.put("taskName",crawlerTaskPO.getTaskName());
                taskDetail.put("comment",crawlerTaskPO.getComment());
                responseResult.getData().add(taskDetail);
            }
        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("获取全部任务出错");
            log.error("listAllTasks error", e);
            return responseResult;
        }
        return responseResult;
    }

    @GetMapping("/data/getTaskAndSiteRule")
    @ResponseBody
    public ResponseResult<Map<String, Object>> getTaskAndSiteRule(HttpServletRequest request) {
        String taskId = request.getParameter("taskId");
        String siteRuleId = request.getParameter("siteRuleId");

        ResponseResult<Map<String, Object>> responseResult = new ResponseResult<>();
        responseResult.setData(new HashMap<>());
        responseResult.setCode(100);
        try {
            // 获取任务模板信息
            responseResult.getData().put("task", crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId)));
            // 获取站点规则信息
            responseResult.getData().put("siteRule", crawlerTaskDao.getCrawlerSiteRule(Integer.parseInt(siteRuleId)));
        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("获取全部任务出错");
            log.error("listAllTasks error", e);
            return responseResult;
        }
        return responseResult;
    }

    @RequestMapping("/createTask")
    @ResponseBody
    public ResponseResult<Boolean> createTask(HttpServletRequest request) throws TopicSpiderException {
        String taskName = request.getParameter("taskName");
        String comment = request.getParameter("comment");
        String priority = request.getParameter("priority");

        CrawlerTaskPO crawlerTaskPO = new CrawlerTaskPO();
        crawlerTaskPO.setComment(comment);
        crawlerTaskPO.setPriority(Integer.parseInt(priority));
        crawlerTaskPO.setStatus(0);
        crawlerTaskPO.setTaskName(taskName);

        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);
        try {
            crawlerTaskDao.createCrawlerTask(crawlerTaskPO);
            responseResult.setData(true);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("增加任务出错");
        }
        return responseResult;
    }


    @RequestMapping("/createTaskWithTemplate")
    @ResponseBody
    public Map<String, String> createTaskWithTemplate(Model model, HttpServletRequest request) throws TopicSpiderException {
        String templateContent = "{\"taskName\":\"T-1001\",\"comment\":\"第一个爬虫任务\",\"priority\":0,\"seedPageRule\":{\"ruleName\":\"种子页面识别\",\"pageType\":1,\"urlRule\":{\"ruleType\":0,\"paramType\":1,\"urlPattern\":\"http://www.mybu.net/link.asp\"}},\"pageRules\":[{\"ruleName\":\"第一层页面识别\",\"pageType\":1,\"urlRule\":{\"ruleType\":1,\"patternType\":1,\"fillHead\":\"http://www.mybu.net/\",\"urlPattern\":\"/html/body/div/center/table/tbody/tr/td/table/tbody/tr/td/div/center/table/tbody/tr/td/a/@href\"},\"fieldRules\":[{\"fieldName\":\"urls\",\"parseType\":1,\"rule\":\"/html/body/div[1]/center[1]/table[2]/tbody[1]/tr[1]/td[2]/table[1]/tbody[1]/tr[1]/td[1]/div[1]/center[1]/table[1]/tbody[1]/tr[4]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/p[1]/a[1]/@href\"}]}]}";
        TaskTemplate taskTemplate = new TaskTemplate(templateContent);
        TaskTemplateResult taskTemplateResult = taskTemplate.create();

        CrawlerTask crawlerTask = taskTemplateResult.getCrawlerTask();

        CrawlerTaskPO crawlerTaskPO = new CrawlerTaskPO();
        crawlerTaskPO.setComment(crawlerTask.getComment());
        crawlerTaskPO.setPriority(crawlerTask.getPriority());
        crawlerTaskPO.setStatus(crawlerTask.getPriority());
        crawlerTaskPO.setTaskName(crawlerTask.getTaskName());
        crawlerTaskDao.createCrawlerTask(crawlerTaskPO);
        crawlerTask.setTaskId(crawlerTaskPO.getId());

        List<PageRule> pageRules = taskTemplateResult.getPageRules();
        for (int i = 0; i < pageRules.size(); i++) {
            PageRule pageRule = pageRules.get(i);
            CrawlerPageRulePO pageRulePO = new CrawlerPageRulePO();
            if (i == 0) {
                pageRulePO.setParentRuleId(-1);
            } else {
                pageRulePO.setParentRuleId(pageRule.getParentRule().getPageId());
            }
            pageRulePO.setPageType(pageRule.getPageType());
            pageRulePO.setPageContentType(pageRule.getPageContentType());
            pageRulePO.setRuleName(pageRule.getRuleName());
            pageRulePO.setLevel(pageRule.getLevel());
            pageRulePO.setTaskId(crawlerTaskPO.getId());
            pageRulePO.setPageTurnRule(pageRule.getPageTurnRule() == null ? null : JSONObject.toJSONString(pageRule.getPageTurnRule()));

            crawlerTaskDao.createCrawlerPageRule(pageRulePO);
            pageRule.setPageId(pageRulePO.getId());

            if (taskTemplateResult.getFieldRules().get(pageRule) == null) {
                continue;
            }
            List<FieldRule> fieldRules = taskTemplateResult.getFieldRules().get(pageRule);
            for (FieldRule fieldRule : fieldRules) {
                CrawlerFieldRulePO crawlerFieldRulePO = new CrawlerFieldRulePO();
                crawlerFieldRulePO.setPageRuleId(pageRulePO.getId());
                crawlerFieldRulePO.setFieldName(fieldRule.getFieldName());
                crawlerFieldRulePO.setParseType(fieldRule.getParseType());
                crawlerFieldRulePO.setRule(fieldRule.getRule());
                crawlerFieldRulePO.setProcessConfig(fieldRule.getProcessConfig());

                crawlerTaskDao.createCrawlerFieldRule(crawlerFieldRulePO);
                fieldRule.setFieldId(crawlerFieldRulePO.getId());
            }
        }

        return new HashMap<>();
    }

    @GetMapping("/showTaskCreating")
    public String showTaskCreating(Model model) {
        return "page/task-creating";
    }

    @GetMapping("/showAllTasks")
    public String showAllTasks(Model model) {
        return "page/task-manager";
    }

}
